import { Controller, Post, Body, UseGuards, Request } from '@nestjs/common'
import { Responser } from '@app/decorators/responser.decorator'
import { QueryParams, QueryParamsResult } from '@app/decorators/queryparams.decorator'
import { LocalLoginDTO, RegisterDTO } from './auth.dto'
import { AuthService } from './auth.service'
import { LoginProvider } from '@app/constants/thirdparty'
import { UserService } from '../user/user.service'
import { AuthUserGuard } from '@app/guards/auth-user.guard'
import { TokenResult } from './auth.interface'

@Controller('auth')
export class AuthController {
  constructor(
    private readonly userService: UserService,
    private readonly authService: AuthService
  ) { }

  @Post('local/login')
  @Responser.handle('本地登录')
  async localLogin(
    @Body() body: LocalLoginDTO,
    @QueryParams() { visitor: { ip } }: QueryParamsResult) {
    const user = await this.authService.validateLocalUser(body.username, body.password)
    if (!user) {
      throw '用户不存在'
    }
    // if (ip) {
    //   this.ipService.queryLocation(ip).then((location) => {
    //     const subject = `应用程序有新的登录活动`
    //     const locationText = location ? [location.country, location.region, location.city].join(' · ') : 'unknow'
    //     const content = `${subject}, IP: ${ip}, 位置: ${locationText}`
    //     this.emailService.sendMailAs(APP.NAME, {
    //       to: APP.ADMIN_EMAIL,
    //       subject,
    //       text: content,
    //       html: content,
    //     })
    //   })
    // }
    return this.authService.generateToken(user)
  }

  @Post('wechat/login')
  @Responser.handle('微信登录')
  async wechatLogin(@Body() body: { code: string }) {
    // return this.authService.handleOAuthLogin(
    //   LoginProvider.WECHAT,
    //   body.code,
    //   {}
    // )
  }

  @Post('qq/login')
  @Responser.handle('QQ登录')
  async qqLogin(@Body() body: {
    access_token: string,
    openid: string;
    unionid: string
    expires_in?: number
    nickname?: string
    avatar?: string
  }) {
    const {
      access_token,
      openid,
      unionid,
      expires_in,
      nickname,
      avatar
    } = body

    // 1. 检查是否绑定
    let user = await this.userService.findByOauth(LoginProvider.QQ, openid)

    // 2. 新用户处理
    if (!user) {
      user = await this.userService.createWithOAuth(
        LoginProvider.QQ,
        openid,
        unionid,
        { access_token, expires_in, nickname, avatar },
      )
    } else {
      // 3. 更新令牌
      await this.userService.updateOAuthToken(
        LoginProvider.QQ,
        openid,
        { access_token, expires_in }
      )
    }

    return {
      id: user._id,
      nickname: user.nickname,
      avatar: user.avatar
    }
  }

  @Post('huawei')
  @Responser.handle('华为账号登录注册')
  async huaweiLogin(@Body() body: { authorizationCode: string; openId: string, unionId: string }) {
    const { authorizationCode, openId, unionId } = body

    // 1. 检查是否绑定
    let user = await this.userService.findByOauth(LoginProvider.HUAWEI, openId)
    // 2. 新用户处理
    if (!user) {
      // 通过 authorizationCode 换取 access_token
      try {
        // 3. 请求华为接口获取 access_token
        const { access_token, refresh_token, expires_in, id_token } = await this.authService.getHuaweiAccessToken(authorizationCode)
        // 4. 通过 access_token 获取用户信息
        const profile = await this.authService.getHuaweiAccountInfo(access_token)
        // 5. 创建用户并绑定
        user = await this.userService.createWithOAuth(
          LoginProvider.HUAWEI,
          openId,
          unionId,
          { access_token, expires_in, refresh_token, ...profile },
        )
        // 6. 返回令牌
        return this.authService.generateToken(user)
      } catch (error) {
        throw '华为登录失败'
      }
    } else {
      // 3. 已有用户，查询令牌是否过期，重新获取令牌，如果没有过期，则继续使用旧令牌
      // const { access_token, refresh_token, expires_in, id_token } = await this.authService.getHuaweiAccessToken(authorizationCode)

      // await this.userService.updateOAuthToken(
      //   LoginProvider.HUAWEI,
      //   openId,
      //   { access_token, expires_in }
      // )
      // 6. 返回令牌
      return this.authService.generateToken(user)
    }
  }

  @Post('register')
  @Responser.handle(('注册'))
  async register(@Body() body: RegisterDTO) {
    if (body.password !== body.confirmPassword) {
      throw '两次输入的密码不一致'
    }
    const user = await this.userService.findByUsername(body.username)

    if (user) {
      throw '该用户已存在'
    }

    return this.userService.createUser(body)
  }

  @Post('refresh')
  @UseGuards(AuthUserGuard)
  @Responser.handle('重置用户凭证')
  renewalToken(@Request() req): TokenResult {
    const user = req.user
    return this.authService.generateToken(user)
  }
}
